package edu.yourl.domain;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import edu.yourl.domain.exception.InvalidDomainInUrlException;
import edu.yourl.domain.service.ServiceLocator;

public class Url extends Gossiper {

	private static final long serialVersionUID = 1L;

	private static final Pattern URL_PATTERN = Pattern
			.compile("(([\\w]+:)?//)?(([\\d\\w]|%[a-fA-f\\d]{2,2})+(:([\\d\\w]|%[a-fA-f\\d]{2,2})+)?@)?([\\d\\w][-\\d\\w]{0,253}[\\d\\w]\\.)+[\\w]{2,4}(:[\\d]+)?(/([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)*(\\?(&?([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})=?)*)?(#([-+_~.\\d\\w]|%[a-fA-f\\d]{2,2})*)?");

	protected String url;
	protected Domain parent;

	public Url(String urlText) {
		this.url = urlText;
		parent = Domain.extractFromUrl(url);
		this.seoFriendlyId = slugify(getFavoritableName());
	}
	
	public String getUrl() {
		return url;
	}
	
	public String getUrlWithProtocolCheck() {
		String protocolUrl = url;
		if (!url.subSequence(0, 4).equals("http")) {
			protocolUrl = "http://" + url;
		}
		return protocolUrl;
	}

	public Domain getParent() {
		return parent;
	}

	@Override
	public void addGossip(Gossip gossip) {
		super.addGossip(gossip);
		parent.addGossip(gossip);
	}

	@Override
	public String getFavoritableName() {
		return url;
	}

	public static List<Url> extractFromText(String message) {
		List<Url> list = new ArrayList<Url>();
		Matcher matcher = URL_PATTERN.matcher(message);
		while (matcher.find()) {
			String urlText = matcher.group();
			Url url = ServiceLocator.getInstance().getFavoritableRepository()
					.findFavoritableByName(Url.class, urlText);
			if (url == null) {
				try {
					url = new Url(urlText);
				} catch (InvalidDomainInUrlException e) {
					// si es el dominio es inválido, se sigue con el próximo,
					// igual es bastante ilógico, ya que sino no hubiese
					// matcheado como URL
					continue;
				}
			}
			list.add(url);
		}
		return list;
	}

	@Override
	public <T> T accept(FavoritableVisitor<T> visitor) {
		return visitor.visit(this);
	}

}
